# encoding: utf-8
# @File  : Sliders_pro.py
# @Author: wu shaofan
# @Date  :  2024/02/13
# @Desc :
import os
import time
import cv2
import numpy as np
import requests
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.wait import WebDriverWait

import conftest
from PO.base.base import Base
from PO.base.get_driver import GetDriver


def base_find_element(driver,loc, timeout=30, poll=0.5):
    return WebDriverWait(driver, timeout=timeout, poll_frequency=poll).until(lambda x: x.find_element(*loc))


# 点击方法
def base_click(driver,loc):
    base_find_element(driver,loc).click()


class SlidersPro:
    def __init__(self, path):
        self.url = path
        # 设置 Chrome WebDriver 路径
        chrome_driver_path = conftest.BASE_DIR + '/tool/chromedriver.exe'
        # 创建 ChromeOptions 对象
        self.options = Options()
        self.options.add_experimental_option("excludeSwitches", ["enable-logging"])
        # 创建 Chrome WebDriver 服务
        service = Service(chrome_driver_path)
        # 创建 Chrome WebDriver 实例
        self.driver = webdriver.Chrome(service=service, options=self.options)
        # 窗口最大化
        self.driver.maximize_window()
        # 打开网页
        self.driver.get(self.url)

    def login(self):
        # 点击 可疑用户-滑动拼图
        loc = 'ul[class="tcapt-tabs__container"] li[captcha-type="jigsaw"]'
        loc = ('css selector', loc)
        base_click(self.driver,loc)

        # 滚动页面滑动条，让滑块显示出来
        js = 'document.documentElement.scrollTop=200'
        self.driver.execute_script(js)


        # 点击完成验证按钮
        loc = 'span[class="yidun_intelli-text"]'
        loc = ('css selector', loc)
        base_click(self.driver, loc)

    # 保存验证码背景图和滑块图
    def save_image(self):
        # 小图片
        loc = ('class name', 'yidun_jigsaw')
        url_s = base_find_element(self.driver, loc).get_attribute('src')

        # 大图片
        loc = ('class name', 'yidun_bg-img')
        url_b = base_find_element(self.driver, loc).get_attribute('src')

        header = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'}
        # 发送请求，获取验证码图片
        response_s = requests.get(url_s, headers=header).content
        response_b = requests.get(url_b, headers=header).content

        # 判断文件夹是否存在不存在则创建'
        os.makedirs('./image/', exist_ok=True)
        # 保存图片
        with open('./image/slider_s.png', 'wb') as f:
            f.write(response_s)

        with open('./image/slider_b.png', 'wb') as f:
            f.write(response_b)

    # 将两张图片先进行灰度处理，再对图像进行高斯处理，最后进行边缘检测
    # 定义为私有方法
    def __handel_img(self, img):
        imgGray = cv2.cvtColor(img, cv2.COLOR_RGBA2GRAY)  # 转灰度图
        imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1)  # 高斯模糊
        imgCanny = cv2.Canny(imgBlur, 60, 60)  # Canny算子边缘检测
        return imgCanny

    # 将JPG图像转变为4通道（RGBA）  定义为私有方法
    def __add_alpha_channel(self, img):
        """ 为jpg图像添加alpha通道 """
        r_channel, g_channel, b_channel = cv2.split(img)  # 剥离jpg图像通道
        # 创建Alpha通道
        alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255
        # 融合通道
        img_new = cv2.merge((r_channel, g_channel, b_channel, alpha_channel))
        return img_new

    # 读取图像
    def match(self, img_s_path, img_b_path):
        # 读取图像
        img_jpg = cv2.imread(img_s_path, cv2.IMREAD_UNCHANGED)
        img_png = cv2.imread(img_b_path, cv2.IMREAD_UNCHANGED)
        # 判断jpg图像是否已经为4通道
        if img_jpg.shape[2] == 3:
            img_jpg = self.__add_alpha_channel(img_jpg)
        img = self.__handel_img(img_jpg)
        small_img = self.__handel_img(img_png)
        res_TM_CCOEFF_NORMED = cv2.matchTemplate(img, small_img, 3)
        value = cv2.minMaxLoc(res_TM_CCOEFF_NORMED)
        value = value[3][0]  # 获取到移动距离
        return value

    # 移动
    def move(self, distance):
        # 获取滑块元素
        loc = 'div[class="yidun_slider  yidun_slider--hover "]'
        loc = ('css selector', loc)
        ele = base_find_element(self.driver, loc)
        # 实例化对象
        action = ActionChains(self.driver)
        # 拖动滑块
        action.drag_and_drop_by_offset(ele, xoffset=distance, yoffset=0).perform()
        # 定位到验证成功
        time.sleep(1)
        loc = '.yidun_tips__text.yidun-fallback__tip'
        loc = ('css selector',loc)
        text = base_find_element(self.driver, loc).text

        if text == "验证成功":
            print("验证成功")
        else:
            print("验证失败")
    @classmethod
    def run(cls,url):
        obj = SlidersPro(url)
        obj.login()
        obj.save_image()
        # 2、对比两张图片，计算忽距离
        small_img = './image/slider_s.png'  # 滑块图（小图片）
        big_img = './image/slider_b.png'  # 背景图（大图片）
        distance = obj.match(small_img, big_img)
        distance = distance / 320 * 300 + 12
        # 3. 移动
        obj.move(distance)


if __name__ == '__main__':
    url = "https://dun.163.com/trial/sense"
    SlidersPro.run(url)


